﻿#define _CRT_SECURE_NO_WARNINGS 1
//深度理解指针5
#include<stdio.h>
//sizeof和strlen的对比
//sizeof---操作符
//int main()
//{
//	int a = 10;
//	printf("%zd\n", sizeof(a));//放置变量或者变量类型
//	printf("%zd\n", sizeof(int));
//	return 0;
//}
//strlen是函数只能只针对字符串---统计\0之前字符的个数
//int main()
//{
//	char arr[] = { "abcdef" };
//	size_t len = strlen(arr);
//	printf("%zd", len);
//	return 0;
//}
//如果字符串中没有\0可能会有越界的风险
//int main()
//{
//	char arr[3] = { 'a','b','c' };
//	size_t len = strlen(arr);
//	printf("%zd", len);
//}
//int main()
//{
//	int a[] = { 1,2,3,4 };
//	printf("%zd\n", sizeof(a));//16---数组名的理解----1、sizeof(数组名)表示整个数组的大小单位是字节------2、&数组名取出的是整个数组的大小
//	printf("%zd\n", sizeof(a + 0));//4或者8---(a+0)表示首元素的地址+0仍然表示首元素的地址，计算的是首元素地址的大小--在x86是4--在x64是8
//	printf("%zd\n", sizeof(*a));//4----首元素地址解引用后就是首元素
//	printf("%zd\n", sizeof(a + 1));//4或者8----表示首元素的地址+1，为第二个元素的地址，仍然计算的是地址的大小--在x86是4--在x64是8
//	printf("%zd\n", sizeof(a[1]));//4----表示数组中第二个元素2（为整型）
//	printf("%zd\n", sizeof(&a));// 4或8---将整个数组的地址取出，仍然是地址，计算后仍未4或者8（&a+1表示跳过整个数组）
//	printf("%zd\n", sizeof(*&a));//16---将整个数组的地址取出并且解引用后为整个数组的元素
//	printf("%zd\n", sizeof(&a + 1));//4或者8----表示跳过整个数组，仍然是地址
//	printf("%zd\n", sizeof(&a[0]));//4或者8------表示首元素的地址
//	printf("%zd\n", sizeof(&a[0] + 1));//4或者8----表示取出首元素地址后+1为第二个元素的地址
//	return 0;
//}
//int main()
//{
//	char arr[] = { 'a','b','c','d','e','f' };
//	printf("%zd\n", sizeof(arr));//6--char类型占1个字节共6个，相乘为6.
//	printf("%zd\n", sizeof(arr + 0));//4或8--（没有单独放到sizeof中）此时arr表示首元素地址，+0后仍未首元素地址
//	printf("%zd\n", sizeof(*arr));//1---表示首元素地址，解引用后为首元素a,为一个字节
//	printf("%zd\n", sizeof(arr[1]));//1--表示第二个元素b
//	printf("%zd\n", sizeof(&arr));//4或者8---取出的是整个数组的地址，但数组的地址仍未地址
//	printf("%zd\n", sizeof(&arr + 1));//4或者8---取出整个数组地址后+1，跳过整个数组的地址但仍为地址
//	printf("%zd\n", sizeof(&arr[0] + 1));//取出首元素地址后 + 1，为第二个元素的地址，仍未地址
//	
//	return 0;
//}
//int main()
//{
//	char arr[] = { 'a','b','c','d','e','f' };
//	printf("%d\n", strlen(arr));//随机值-----求得是字符串的长度统计\0之前元素的个数（字符数组中不包含\0,会越界！）
//	printf("%d\n", strlen(arr + 0));//随机值-------arr是首元素的地址，向后寻找直到\0结束。
//	printf("%d\n", strlen(*arr));//报错!-----首元素地址解引用后为首元素！strlen需要传递的是地址，但此时传递的是首元素a--ascll码为97,strlen会将97作为地址向后统计字符串的长度，97作为地址的空间不一定属于该程序，不一能访问！会报错！
//	printf("%d\n", strlen(arr[1]));//报错!-----与上一个类似！
//	printf("%d\n", strlen(&arr));//随机值将整个数组的地址传递给strlen,strlen从该地址向后访问直到\0结束
//	printf("%d\n", strlen(&arr + 1));//随机值
//	printf("%d\n", strlen(&arr[0] + 1));//随机值
//
//	return 0;
//}
//int main()
//{
//	char arr[] = "abcdef";
//	printf("%zd\n", sizeof(arr));// 7---统计字符串中元素的个数[a b c d e f \0]
//	printf("%zd\n", sizeof(arr + 0));//4或8首元素地址
//	printf("%zd\n", sizeof(*arr));//1---首元素地址解引用后为a
//	printf("%zd\n", sizeof(arr[1]));//1
//	printf("%zd\n", sizeof(&arr));//4或者8，取出的是数组的地址，仍为地址
//	printf("%zd\n", sizeof(&arr + 1));//4或者8
//	printf("%zd\n", sizeof(&arr[0] + 1));//4或者8
//
//	return 0;
//}
//int main()
//{
//	char arr[] = "abcdef";
//	printf("%zd\n", strlen(arr));//6   此时arr是数组首元素地址----\0之前字符的个数
//	printf("%zd\n", strlen(arr + 0));//6
//	printf("%zd\n", strlen(*arr));// 报错！  此时arr是数组首元素地址，解引用后为数组首元素
//	printf("%zd\n", strlen(arr[1]));//报错！
//	printf("%zd\n", strlen(&arr));// 6 此时取出的是整个数组的地址，但也是从数组首元素的位置开始
//	printf("%zd\n", strlen(&arr + 1));// 随机值 取出整个数组的地址，+1后会跳过整个数组！
//	printf("%zd\n", strlen(&arr[0] + 1));//取出的是数组首元素地址+1后为数组第二个元素的地址！
//	return 0;
//}
//int main()
//{
//	char* p = "abcdef";//是将a的地址赋值给p
//	printf("%zd\n", sizeof(p));//4或者8，p是指针变量！
//	printf("%zd\n", sizeof(p + 1));//4或者8  p中存放的是数组首元素地址+1后变为数组第二个元素的地址，也是指针
//	printf("%zd\n", sizeof(*p));//  1   p存放是数组首元素的地址，解引用后为数组第一个元素，a大小为一个字节
//	printf("%zd\n", sizeof(p[0]));  //p[0]为数组首元素,大小为1
//	printf("%zd\n", sizeof(&p));// 4或者8  p是数组首元素地址，在对其取地址
//	printf("%zd\n", sizeof(&p + 1));//  4或者8   同理上一个（取出整个数组的地址+1后跳过整个数组）
//	printf("%zd\n", sizeof(&p[0] + 1));
//	return 0;
//}
//int main()
//{
//	char* p = "abcdef";
//	printf("%zd\n", strlen(p));// 6----p是首元素地址
//	printf("%zd\n", strlen(p + 1));//5---指向b的地址
//	printf("%zd\n", strlen(*p));// 报错 *p为a
//	printf("%zd\n", strlen(p[0])); //报错* p为a
//	printf("%zd\n", strlen(&p));//p是数组首元素地址，在将地址取出存放到另一个指针变量中后面有没有\0未知！
//	printf("%zd\n", strlen(&p + 1));//同理
//	printf("%zd\n", strlen(&p[0] + 1));//从第二个元素的地址开始！
//
//	return 0;
//}
//int main()
//{
//	int a[3][4] = { 0 };
//	printf("%zd\n", sizeof(a));//   48   a代表整个数组3*4*4=48
//	printf("%zd\n", sizeof(a[0][0]));//   4
//	printf("%zd\n", sizeof(a[0]));//   16  a[0]是第一行的数组名，现在单独放在sizeof内部，计算的是一行的大小
//	printf("%zd\n", sizeof(a[0] + 1));// 4 或者 8  a[0]没有单独放在sizeof内部，表示第一行一维数组首元素地址，+1为第二个元素的地址！
//	printf("%zd\n", sizeof(*(a[0] + 1)));// 4 第一行第二个元素为int类型 
//	printf("%zd\n", sizeof(a + 1));//4 或者 8   a作为二维数组的数组名没有单独放在sizeof中，a为数组首元素地址即为第一行的地址+1后跳过第一行为第而行的地址
//	printf("%zd\n", sizeof(*(a + 1)));//  16  继上面解引用后为第二行的元素
//	printf("%zd\n", sizeof(&a[0] + 1));//  4或8  a[0]是第一行的数组名，&a[0]为第一行的地址，&a[0]+1为第二行的地址
//	printf("%zd\n", sizeof(*(&a[0] + 1)));//   16   继上面解引用后为第二行的元素
//	printf("%zd\n", sizeof(*a));//   16     a为首元素地址即第一行的地址，解引用后为第一行的元素
//	printf("%zd\n", sizeof(a[3]));//   16  虽然不会有第4行数组名，但sizeof不会真实访问！仅仅是通过类型进行推到！为第4行的数组
//	return 0;
//}
//主要是对数组名的理解！

//指针运算:

//#include <stdio.h>
//int main()
//{
//	int a[5] = { 1, 2, 3, 4, 5 };//a的类型为数组指针int(*)a
//	int* ptr = (int*)(&a + 1);
//	printf("%d,%d", *(a + 1), *(ptr - 1));//2   5
//	return 0;
//}
//
//在X86环境下​
//假设结构体的大小是20个字节​
//程序输出的结果是啥？
//#include<stdio.h>
//struct Test
//{
//	int Num;
//	char* pcName;
//	short sDate;
//	char cha[2];
//	short sBa[4];
//}*p = (struct Test*)0x100000;
//int main()
//{
//	printf("%p\n", p + 0x1);
//	printf("%p\n", (unsigned long)p + 0x1);
//	printf("%p\n", (unsigned int*)p + 0x1);
//	return 0;
//}
//#include <stdio.h>
//int main()
//{
//	
//	int a[3][2] = { (0, 1), (2, 3), (4, 5) };//逗号表达式！,会从左向右一次计算
//	int* p;//正常赋值应该为{{0，1}，{2，3}，{4，5}}
//	p = a[0];
//	printf("%d", p[0]);
//	return 0;//1
//}
//  1  3
//  5  0
//  0  0
// 
//#include <stdio.h>
//int main()
//{
//	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	int* ptr1 = (int*)(&aa + 1);
//	int* ptr2 = (int*)(*(aa + 1));
//	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
//	return 0;
//}
//10   5
//1 2 3 4 5
//6 7 8 9 10-ptr1
//ptr2
//假设环境是x86环境，程序输出的结果是啥？​
//#include <stdio.h>
//int main()
//{
//	int a[5][5];
//	int(*p)[4];//数组指针
//	p = a;
//	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
//	return 0;//指针减去指针为元素个数   
//}//二进制转换成16进制：每4个二进制位转换成一个16进制位
//a[5][5]
// 0 0 0 0 0
// 0 0 0 0 0
// 0 0 0 0 0
// 0 0 0 0 0
// 0 0 0 0 0
//     |
//#include <stdio.h>
//int main()
//{
//	char* a[] = { "work","at","alibaba" };
//	char** pa = a;
//	pa++;
//	printf("%s\n", *pa);
//	return 0;
//}
//#include <stdio.h>
//int main()
//{
//	char* c[] = { "ENTER","NEW","POINT","FIRST" };
//	char** cp[] = { c + 3,c + 2,c + 1,c };
//	char*** cpp = cp;
//	printf("%s\n", **++cpp);
//	printf("%s\n", *-- * ++cpp + 3);
//	printf("%s\n", *cpp[-2] + 3);
//	printf("%s\n", cpp[-1][-1] + 1);
//	return 0;
//}

//POINT//ER//ST//EW